package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"
)

func main03() {
	//var fp *File
	//fp是结构体指针
	//os.Create创建文件时,文件不存在会创建一个新文件,如果文件存在会覆盖原内容
	fp, err := os.Create("./test.txt")
	if err != nil {
		fmt.Println(err)
		return
	}

	//延迟调用,关闭文件
	//如果文件描述符不关闭
	//1、占用内存和缓冲区
	//2、文件打开有上限(65535),如果满了再打开文件描述符就会失败
	defer fp.Close()

	fp.Write([]byte("hello world\n"))
	fp.WriteString("一叶知秋\n")
}

func main() {
	filePath := "/opt/wwwroot/go/go_learn/test.txt"
	//1、在文件指定位置写入数据
	writeAt(filePath)

	//2、在文件末尾写入数据
	appendFile(filePath)

	//3、检测文件是否存在
	fileExists := checkFileExists(filePath)
	fmt.Printf("%s %v\n", filePath, fileExists)

	//4、读文件方式1
	readFile(filePath)

	//5、读取文件方式2
	readFileLine(filePath)

	//6、一次行读取文件(适合文件不太大的情况)
	onceReadFile(filePath)

	filePath2 := "/opt/wwwroot/go/go_learn/test2.txt"
	//7、创建一个文件输入(缓冲读取需要使用Flush)
	bufioWrite(filePath2)

	//8、打开已有文件,覆盖原内容写入
	coverWrite(filePath2)

	//9、以追加方式写入文件
	appendWrite(filePath2)

	//10、打开已存在的文件,读取原文件内容,并追加数据
	readAndAppend(filePath2)

	//11、将一个文件的内容写到另一个文件当中
	ext := path.Ext(filePath2)
	dir, base := path.Split(filePath2)
	fileName := strings.Split(base, ".")[0]
	filePath3 := fmt.Sprintf("%s%s_copy%s", dir, fileName, ext)
	copyFile1ToFile2(filePath2, filePath3)
	appendWrite(filePath3)

	//12、copy文件,有问题
	copyFile(filePath2)
}

//在文件的指定位置写入数据
func writeAt(path string) {
	//1、以可读可写方式打开文件
	//os.OpenFile不能创建新文件
	//os.OpenFile(文件名,打开模式,打开权限)
	//os.O_RDWR:可读可写模式
	fp, err := os.OpenFile(path, os.O_RDWR, 0660)
	defer fp.Close()
	if err != nil {
		fmt.Println(err)
	}

	//获取文件当前游标指针所在位置,在文件末尾写入数据
	n, err := fp.Seek(0, io.SeekEnd)
	if err != nil {
		fmt.Println(err)
		return
	}
	fp.WriteAt([]byte("foo\n"), n)
}

//在文件末尾追加内容
func appendFile(path string) {
	//以可读可写方式打开文件,且指针在文件的末尾
	fp, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND, 0660)
	defer fp.Close()
	if err != nil {
		fmt.Println(err)
		return
	}

	fp.Write([]byte("bar\n"))
	fp.WriteString("bar1\n")
}

//检测文件是否存在
func checkFileExists(path string) bool {
	_, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		return false
	} else {
		return true
	}
}

//读取文件
func readFile(path string) {
	if !checkFileExists(path) {
		log.Fatal("文件不存在")
	}
	//以只读方式打开文件
	fp, err := os.Open(path)
	defer fp.Close()
	if err != nil {
		fmt.Println(err)
	}

	buf := make([]byte, 1024*2)
	//n, err := fp.Read(buf)
	//if err != nil {
	//	fmt.Println(err)
	//}

	for{
		n,err:=fp.Read(buf)
		if err != nil && err == io.EOF{
			break
		}
		fmt.Println(string(buf[:n]))
	}
	//fmt.Println("readFile读取文件：", string(buf[:n]))
}

//读取文件,一次读取一行
func readFileLine(path string) {
	if !checkFileExists(path) {
		fmt.Println("文件不存在")
		return
	}
	fp, err := os.Open(path)
	defer fp.Close()
	if err != nil {
		fmt.Println(err)
		return
	}

	buf := bufio.NewReader(fp)
	for {
		str, err := buf.ReadString('\n')
		fmt.Println(str)
		if err != nil && err == io.EOF {
			break
		}
	}
}

//一次行读取文件(适合文件不太大的情况)
func onceReadFile(path string) {
	reader, err := ioutil.ReadFile(path)
	if err != nil {
		fmt.Println(err)
	}
	//fmt.Println(reader)
	fmt.Println(string(reader))
}

//创建一个文件输入(缓冲读取需要使用Flush)
func bufioWrite(path string) {
	//以只写和创建文件方式打开文件,如果文件已存在会清空文件的原内容
	fp, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0660)
	defer fp.Close()
	if err != nil {
		fmt.Println(err)
	}

	str := "hello world\n"
	writer := bufio.NewWriter(fp)
	for i := 0; i <= 5; i++ {
		writer.WriteString(str)
	}
	//使用bufio.Writer数据会先写入缓存,所以需要使用Flush才可以真正写入到文件
	writer.Flush()
}

//覆盖写入文件
func coverWrite(path string) {
	fp, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0660)
	defer fp.Close()
	if err != nil {
		fmt.Println(err)
	}

	writer := bufio.NewWriter(fp)
	for i := 0; i <= 10; i++ {
		writer.WriteString("foo bar\n")
	}
	writer.Flush()
}

//以追加方式写入文件
func appendWrite(path string) {
	fp, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND, 0660)
	defer fp.Close()
	if err != nil {
		fmt.Println(err)
		return
	}

	writer := bufio.NewWriter(fp)
	writer.WriteString("hello world\n")
	writer.Flush()
}

//打开已存在的文件,读取原文件内容,并追加数据
func readAndAppend(path string) {
	fp, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND, 0660)
	defer fp.Close()
	if err != nil {
		fmt.Println(err)
		return
	}

	reader := bufio.NewReader(fp)
	for {
		str, err := reader.ReadString('\n')
		if err != nil && err == io.EOF {
			break
		}
		fmt.Println(str)
	}

	writer := bufio.NewWriter(fp)
	writer.WriteString("追加的内容\n")
	writer.WriteString("追加的内容1\n")
	writer.Flush()
}

//将一个文件的内容写到另一个文件当中去
func copyFile1ToFile2(path1, path2 string) {
	fp1, err := os.OpenFile(path1, os.O_RDONLY, 0660)
	defer fp1.Close()
	if err != nil {
		fmt.Println(err)
		return
	}

	fp2, err := os.OpenFile(path2, os.O_WRONLY|os.O_CREATE, 0660)
	if err != nil {
		fmt.Println(err)
		return
	}

	reader := bufio.NewReader(fp1)
	//writer := bufio.NewWriter(fp2)
	for {
		str, err := reader.ReadString('\n')
		if err != nil && err == io.EOF {
			break
		}
		//fmt.Println(str)
		//writer.WriteString(str)
		fp2.WriteString(str)
	}
	//writer.Flush()
	defer fp2.Close()
}

func copyFile(path string) {
	srcFp, err := os.Open(path)
	defer srcFp.Close()
	if err != nil {
		fmt.Println(err)
		return
	}

	descFilePath := getCopyFileName(path)
	destFp, err := os.OpenFile(descFilePath, os.O_RDWR|os.O_CREATE, 0660)
	defer destFp.Close()
	if err != nil {
		fmt.Println(err)
		return
	}

	reader := bufio.NewReader(srcFp)
	writer := bufio.NewWriter(destFp)
	res, err := io.Copy(writer, reader)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("copy结果", res)
}

func getCopyFileName(filePath string) (copyFilePath string) {
	ext := path.Ext(filePath)
	dir, base := path.Split(filePath)
	fileName := strings.Split(base, ".")[0]
	copyFilePath = fmt.Sprintf("%s%s_copy1%s", dir, fileName, ext)
	return
}
